import axios from 'axios'
import { StatusCode, RequestEnum } from '@/config/httpEnums'
import { ElMessage } from 'element-plus'

const axiosInstanceConfig = {
  baseURL: import.meta.env.VITE_BASE_URL,
  timeout: 600000,
}

export class HttpService {
  _axiosInstance = null
  static _httpService = new HttpService()

  constructor() {
    if (!this._axiosInstance) {
      this._axiosInstance = this.creatInstance()
    }
  }

  creatInstance() {
    const result = axios.create(axiosInstanceConfig)
    this.setupInterceptors(result)
    return result
  }

  static getInstance() {
    return HttpService._httpService
  }

  setupInterceptors(instance) {
    instance.interceptors.response.use(
      (res) => {
        if (res.status !== StatusCode.RESPONSE_SUCCESS) {
          ElMessage.error(res.statusText || '网络错误!')
        }

        if (res.headers['content-type'] === 'application/octet-stream') {
          return res
        }

        if (res.data.code !== StatusCode.SUCCESS) {
          if (res.data.code === StatusCode.PERMISSION_DENIED) {
          }
          ElMessage.error({ message: res.data.message, grouping: true })
        }
        return res.data
      },
      (error) => {
        return error
      }
    )

    instance.interceptors.request.use(
      (request) => {
        return request
      },
      (error) => {
        return error
      }
    )
  }

  setHeader(headers) {
    if (!this._axiosInstance) {
      return
    }
    Object.assign(this._axiosInstance.defaults.headers, headers)
  }

  /**
   * @description Upload File
   */
  uploadFile(config, params) {
    const formData = new FormData()
    const customFilename = params.name || 'file'

    formData.append(customFilename, params.file)

    if (params.data) {
      Object.keys(params.data).forEach((key) => {
        const value = params.data[key]
        formData.append(key, value)
      })
    }

    return this.request({
      ...config,
      method: RequestEnum.POST,
      data: formData,
      headers: {
        'Content-type': ContentTypeEnum.FORM_DATA,
      },
    })
  }

  get(config) {
    return this.request({ ...config, method: RequestEnum.GET })
  }

  post(config) {
    return this.request({ ...config, method: RequestEnum.POST })
  }

  put(config) {
    return this.request({ ...config, method: RequestEnum.PUT })
  }

  delete(config) {
    return this.request({ ...config, method: RequestEnum.DELETE })
  }

  request(config) {
    return new Promise((resolve, reject) => {
      this._axiosInstance
        .request(config)
        .then((res) => {
          resolve(res)
        })
        .catch((e) => {
          reject(e)
        })
    })
  }
}

export const service = HttpService.getInstance()
